Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for renaming columns within a table #689

Merged
merged 5 commits into from
Feb 14, 2020
Merged

Conversation

gjeck
Copy link
Collaborator

@gjeck gjeck commented Jan 23, 2020

Summary:

This adds support for renaming columns within a table using ALTER TABLE table RENAME COLUMN oldname TO newname.

SQLite 3.25.0 introduced this feature in 2018 and newer os versions should have bundled versions higher than 3.25.0. Unfortunately, this is not true for macOS.

Example:

try db.alter(table: "player") { t in
  t.rename(column: "url", to: "home_url")
}

Pull Request Checklist:

Wasn't sure if I should update documentation for a feature only available on very new os versions.

  • This pull request is submitted against the development branch.
  • Inline documentation has been updated.
  • README.md or another dedicated guide has been updated.
  • Changes are tested.

@groue
Copy link
Owner

groue commented Jan 23, 2020

Welcome back @gjeck, this is a great addition!

I'll be off for a few weeks, but I'll be glad to merge your pull request when I'm back.

Quick notes:

I would be glad if the feature would be enabled when possible: custom SQLite, SQLCipher, maybe some versions of macOS, and maybe not all versions of iOS, tvOS, and warchOS. This is not a very fun task, I agree, but it's a habit here.

Also, it looks like the feature does not need to use ColumnDefinition, and that plain Strings would be just enough.

Don't feel compelled to address those points, but they both look like they have to be solved before the changes are shipped on master.

@gjeck
Copy link
Collaborator Author

gjeck commented Jan 23, 2020

Thank you for the notes @groue! I will make sure to get those changes in.

It looks like custom sqlite is pinned at 3.30.1 so that should be straightforward to support. Do you happen to have an area of the code shedding light on the version requirements of SQLCipher? Apologies, but I am not familiar with this 😅

@groue
Copy link
Owner

groue commented Jan 23, 2020

Sure @gjeck!

Check for example the definition of DatabaseMigrator.registerMigrationWithDeferredForeignKeyCheck(_:). It's a mix of #if and @available checks.

As you see, we can't avoid some duplication of code and documentation. This is real ugly, but this is what we need for our feature :-)

@gjeck
Copy link
Collaborator Author

gjeck commented Jan 23, 2020

From the failed build on de6f9b7 it looks like SQLCipher version ~3 has issues, while SQLCipher version ~4 seems ok. I'm not sure how to check for the SQLCipher version to account for this.

If there was a way we could expose SQLITE_VERSION_NUMBER then we could maybe not dig into specific SQLCipher versions and just check #if SQLITE_VERSION_NUMBER >= 3025000, but I'm not sure if that's something that is desirable to expose.

@groue
Copy link
Owner

groue commented Jan 24, 2020

SQLCipher tests don't have good Travis logs (I hadn't the opportunity to fix this).

  1. Merge or rebase your branch on the development branch: it contains fixes for earlier versions of Xcode.

  2. If you want to run SQLCipher tests, go to Tests/CocoaPods/SQLCipher3 or Tests/CocoaPods/SQLCipher4, run pod install in the Terminal, open GRDBTests.xcworkspace, and run tests.

@groue
Copy link
Owner

groue commented Jan 24, 2020

it looks like SQLCipher version ~3 has issues

Indeed SQLCipher 3.4.2 reports... SQLite version 3.24.0:

String.fetchOne(db, sql: "PRAGMA cipher_version") // "3.4.2"
sqlite3_libversion_number()                       // 3024000

The need for distinguishing SQLCipher 3 from SQLCipher 4 has not arisen yet, so we enter uncharted territory :-)

If there was a way we could expose SQLITE_VERSION_NUMBER then we could maybe not dig into specific SQLCipher versions and just check #if SQLITE_VERSION_NUMBER >= 3025000, but I'm not sure if that's something that is desirable to expose.

Swift can't perform such check. There is no C preprocessor :-)

Let's not block this pull request with this problem:

  1. I'm OK if the API is available for SQLCipher 3. I expect it will throw an SQL syntax error at runtime. We'll work around this with explicit documentation.
  2. Guard your tests with if sqlite3_libversion_number() >= 3025000

@groue
Copy link
Owner

groue commented Jan 24, 2020

In order to reduce code duplication, you can:

#if ...
/// doc...
public func foo(...) { _foo(...) }
#else
/// doc...
@available(...)
public func foo(...) { _foo(...) }
#endif

private func _foo(...) { /* the real job */ }

gjeck added 4 commits January 24, 2020 08:46
SQLite introduced enhancements to the `ALTER TABLE` command in 3.25.0.
iOS 13.0+, macOS 10.15+, tvOS 13.0+, and watchOS 6.0+ have a SQLite
library bundled higher than 3.25.0.

For more information see https://www.sqlite.org/lang_altertable.html
Note: SQLCipher3 will have the new column rename method exposed, but it
will throw an error at runtime if used.
@gjeck
Copy link
Collaborator Author

gjeck commented Jan 24, 2020

@groue thank you for all the additional details! I hope I'm not pulling you away from a vacation or anything. d14ac3e should address all comments 🤞. No rush to review/approve 🍹.

@groue
Copy link
Owner

groue commented Jan 24, 2020

Yeah, I'm leaving tomorrow :-) Don't expect any answer until mid February. I'll be happy to catch up then :-)

@gjeck
Copy link
Collaborator Author

gjeck commented Jan 24, 2020

Sounds great! Enjoy your time off 🌴

@groue groue merged commit a5b2757 into development Feb 14, 2020
@groue
Copy link
Owner

groue commented Feb 14, 2020

Thank you very much @gjeck, this is perfect :-)

@groue groue deleted the rename-column branch February 14, 2020 10:27
groue added a commit that referenced this pull request Feb 14, 2020
@groue
Copy link
Owner

groue commented Feb 23, 2020

Shipped in v4.10.0! Sorry for the delay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants